﻿
Imports std
Imports System.Net

Public Class tcpTalkGate
    Public destaddress As String = Nothing
    Public destport As Int32 = Nothing
    Protected WithEvents server As tcpServer2 = Nothing
    Protected contextSet As map(Of IPEndpoint2, tcpTalk) = Nothing

    Public Property destination() As IPEndPoint
        Get
            Return New IPEndPoint(destaddress, destport)
        End Get
        Set(ByVal value As IPEndPoint)
            destaddress = Convert.ToString(value.Address)
            destport = value.port
        End Set
    End Property

    Public Property maxConnCount() As Int32
        Get
            assert(Not server Is Nothing, "server is nothing before get maxConnCount")
            Return server.maxConnCount
        End Get
        Set(ByVal value As Int32)
            assert(Not server Is Nothing, "server is nothing before set maxConnCount")
            server.maxConnCount = value
        End Set
    End Property

    Public Function connCount() As Int32
        assert(Not server Is Nothing, "server is nothing before get connCount")
        Return server.connCount
    End Function

    Public Function tcpListener() As tcpListener2
        assert(Not server Is Nothing, "server is nothing before get tcpListener")
        Return server.tcpListener
    End Function

    Public Property port() As Int32
        Get
            assert(Not server Is Nothing, "server is nothing before get port")
            Return server.port
        End Get
        Set(ByVal value As Int32)
            assert(Not server Is Nothing, "server is nothing before set port")
            server.port = value
        End Set
    End Property

    Public Sub reset()
        server.reset()
    End Sub

    Public Sub [stop]()
        server.stop()
    End Sub

    Public Function start() As Boolean
        Return server.start()
    End Function

    Public Function start(ByVal newport As Int32) As Boolean
        Return server.start(newport)
    End Function

    Public Sub New()
        server = New tcpServer2()
        contextSet = New map(Of IPEndpoint2, tcpTalk)
    End Sub

    Private Sub server_receive(ByVal handle As tcpServer2.talkHandle) Handles server.receive
        Dim ip As IPEndPoint = Nothing
        ip = handle.remoteIPEndPoint

        Dim it As map(Of IPEndpoint2, tcpTalk).iterator = Nothing
        it = contextSet.find(ip)
        If it = contextSet.end() Then
            it = contextSet.insert(ip, New tcpTalk())
        End If

        With (+it)
            .second.host = destaddress
            .second.port = destport
            .second.sendData = handle.receiveData
            If Not .second.talk() Then
                raiseError("cannot send data to destination, address " + destaddress _
                           + ", port " + Convert.ToString(destport), errorHandle.errorType.system)
            ElseIf Not handle.return(.second.receiveData) Then
                raiseError("cannot return reply to source, address " + Convert.ToString(ip.Address) _
                           + ", port" + Convert.ToString(ip.Port), errorHandle.errorType.system)
            End If
        End With
    End Sub

    Public Shared Sub unittest()
        Dim gate As tcpTalkGate = Nothing
        gate = New tcpTalkGate
retrySrcPort:
        Console.WriteLine("input source / local port")
        If Not convertor.toint32(Console.ReadLine(), gate.port) Then
            GoTo retrySrcPort
        End If
        Console.WriteLine("input destination address")
        gate.destaddress = Console.ReadLine()
retryDestPort:
        Console.WriteLine("input destination port")
        If Not convertor.toint32(Console.ReadLine(), gate.destport) Then
            GoTo retryDestPort
        End If

        If Not gate.start() Then
            raiseError("cannot start tcpTalkGate", errorHandle.errorType.exclamation)
        End If
    End Sub
End Class
